﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using PhiStore.Generics;
using PhiStore.Policies;
using PhiStore.ReturnCodes;

namespace PhiStore.ExampleCodes.PhiMovieStreamer
{

    public static class MovieGenerator
    {
        public static string movieTitle = "phi_the_loop";

        /// <summary>
        /// Reads the movie into memory.
        /// Well - not all of the movie, 'cause its too big
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<Bitmap> GenerateMovie()
        {
            List<Bitmap> result = new List<Bitmap>();
            try
            {
                Generate();
            }
            catch (PhiException)
            {
                //it already exist - thank god
            }

            PhiClient<Bitmap> client = new PhiClient<Bitmap>(false, true);
            client.Initialize();
            client.Connect();

            long frameCount = client.ListCount(movieTitle);

            for (long i = 1502; i < frameCount; i++)
            {
                result.Add(client.ListRead(movieTitle, i));
            }

            client.Disconnect();
            return result;
        }

        /// <summary>
        /// Creates a PhiArray which uses prefetching
        /// </summary>
        /// <param name="chunkSize"></param>
        /// <returns></returns>
        public static PhiArray<Bitmap> GenerateMovie(long chunkSize, bool enableClientPrefetching)
        {
            string key = movieTitle + "_" + chunkSize.ToString();

            try
            {
                Generate();
            }
            catch(PhiException)
            {
                //it already exist - thank god
            }

            PhiClient<object> client = new PhiClient<object>(false, enableClientPrefetching);
            client.Initialize();
            client.Connect();
            
            long frameCount = client.ListCount(movieTitle);

            try
            {
                PhiArray<Bitmap> array = new PhiArray<Bitmap>(client, key, frameCount, chunkSize);
                for (long i = 0; i < frameCount; i++)
                {
                    Bitmap frame = (Bitmap)client.ListRead(movieTitle, i);
                    array[i] = frame;
                }
                return array;
            }
            catch
            {
                return new PhiArray<Bitmap>(client, key);
            }
        }

        public static void Generate()
        {
            Bitmap Frame1 = (Bitmap)
                Bitmap.FromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("PhiStore.Resources.1.png"));

            Bitmap Frame2 = (Bitmap)
                Bitmap.FromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("PhiStore.Resources.2.png"));

            Bitmap Frame3 = (Bitmap)
               Bitmap.FromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("PhiStore.Resources.3.png"));

            Bitmap Frame4 = (Bitmap)
               Bitmap.FromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("PhiStore.Resources.4.png"));

            PhiClient<Bitmap> client = new PhiClient<Bitmap>(false, false);
            client.Initialize();
            client.Connect();

            Policy policy = Policies.Examples.Log;
            policy.MayGarbageCollect = false;
            policy.IdleThreshold = 15 * 60 * 1000;
            policy.ReplicationNumber = 1;
            
            

            try
            {
                client.ListCreate(movieTitle, new List<Bitmap>(), policy);
            }
            catch (PhiException)
            {
                return;
            }
            AddFrame(Frame1, client);
            AddFrame(Frame2, client);
            AddFrame(Frame3, client);
            AddFrame(Frame4, client);

            client.Disconnect();
        }

        private static void AddFrame(Bitmap Frame1, PhiClient<Bitmap> client)
        {
            Color current = Color.FromArgb(255, 5, 5, 5);

            client.ListAppend(movieTitle, ExchangeColor(Color.White, current, Frame1));

            while (!(current.R == 255 && current.G == 255 && current.B == 255))
            {
                Color newColor = NextColor(current);
                client.ListAppend(movieTitle, ExchangeColor(current, newColor, Frame1));
                Console.WriteLine(newColor.ToString());
                current = newColor;
            }
        }

        private static Color NextColor(Color PreviousColor)
        {
            Color newColor = Color.FromArgb(255,
                PreviousColor.R == 255 ? 255 : PreviousColor.R + 1,
                PreviousColor.R < 255 ? PreviousColor.G : (PreviousColor.G == 255 ? 255 : PreviousColor.G + 1),
                PreviousColor.G < 255 ? PreviousColor.B : (PreviousColor.B == 255 ? 255 : PreviousColor.B + 1)
                );
            return newColor;
        }

        private static Bitmap ExchangeColor(Color oldColor, Color newColor, Bitmap image)
        {
            for (int x = 0; x < image.Width; x++)
            {
                for (int y = 0; y < image.Height; y++)
                {
                    Color c = image.GetPixel(x, y);
                    if (c.R == oldColor.R && c.G == oldColor.G && c.B == oldColor.B)
                    {
                        image.SetPixel(x, y, newColor);
                    }
                }
            }
            return image;
        }

    }
}
